package com.mzj.saas.mservice.announcement.service;

import com.mzj.saas.commons.ResultBean;
import com.mzj.saas.commons.StatusCode;
import com.mzj.saas.commons.enums.OSSUploadFileTypeEnum;
import com.mzj.saas.commons.util.StringUtils;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.mservice.announcement.entity.Announcement;
import com.mzj.saas.mservice.announcement.entity.AnnouncementUser;
import com.mzj.saas.mservice.announcement.repository.AnnouncementRepository;
import com.mzj.saas.mservice.announcement.repository.AnnouncementUserRepository;
import com.mzj.saas.mservice.announcement.vo.AnnouncementUserVO;
import com.mzj.saas.mservice.announcement.vo.AnnouncementVO;
import com.mzj.saas.mservice.application.vo.DepartmentHierarchyVO;
import com.mzj.saas.mservice.area.entity.Area;
import com.mzj.saas.mservice.area.repository.AreaRepository;
import com.mzj.saas.mservice.community.entity.Community;
import com.mzj.saas.mservice.community.repository.CommunityRepository;
import com.mzj.saas.mservice.eligible.entity.DepartmentHierarchy;
import com.mzj.saas.mservice.eligible.repository.DepartmentHierarchyRepository;
import com.mzj.saas.mservice.oss.service.OSSService;
import com.mzj.saas.redis.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class AnnouncementService {
    private static final Logger LOG = LoggerFactory.getLogger(AnnouncementService.class);
    @Autowired
    private RedisService redisService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private OSSService ossService;
    @Autowired
    private AnnouncementRepository announcementRepository;
    @Autowired
    private DepartmentHierarchyRepository departmentHierarchyRepository;
    @Autowired
    private AnnouncementUserRepository announcementUserRepository;
    @Autowired
    private CommunityRepository communityRepository;
    @Autowired
    private AreaRepository areaRepository;
    /**
     * OSS 域名
     */
    @Value("${ali.oss.endpoint}")
    private String endpoint;
    /*
     *oss地址
     */
    @Value("${ali.oss.bucket}")
    private String bucket;
    @Autowired
    @Qualifier("stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    /*
     *公告详情显示
     */
    public ResultBean<Object> advertDetailShow(String accessToken, Long id) {
        LOG.info("AnnouncementService advertDetailShow accessToken={},id={}", accessToken, id);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            AnnouncementUserVO announcementUserVO = new AnnouncementUserVO();
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            if (id == null) {
                result.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return result;
            }
            announcementUserVO.setAnnouncementId(id);
            announcementUserVO.setUserId(tokenRedisVo.getId());
            announcementUserVO.setViewTime(new Date());
            Optional<Announcement> existAnnouncement = announcementRepository.findById(id);
            AnnouncementUser existAnnouncementUser = announcementUserRepository.findByAnnouncementIdAndUserId(id, tokenRedisVo.getId());
            if (existAnnouncementUser == null) {
                announcementUserVO.setStatus(0);
            } else {
                announcementUserVO.setId(existAnnouncementUser.getId());
                announcementUserVO.setStatus(existAnnouncementUser.getStatus());
                announcementUserVO.setThumbTime(existAnnouncementUser.getThumbTime());
            }
            AnnouncementUser announcementUser = new AnnouncementUser();
            BeanUtils.copyProperties(announcementUserVO, announcementUser);
            announcementUserRepository.save(announcementUser);
            // 新增：如果是社区/小区公告，展示名称   类型：1企业公告 2社区公告 3小区公告 4平台广告 5公租房公示
            if (existAnnouncement.get().getType() == 2) {
                Long areaId = existAnnouncement.get().getAreaId();
                Optional<Area> area = areaRepository.findById(areaId);
                String areaName = area.get().getName();
                existAnnouncement.get().setAreaName(areaName);

            }
            if (existAnnouncement.get().getType() == 3) {
                String communityId = existAnnouncement.get().getCommunityId();
                Optional<Community> community = communityRepository.findById(communityId);
                String communityName = community.get().getName();
                existAnnouncement.get().setCommunityName(communityName);
            }
            result.setResultData(existAnnouncement);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }


    /*
     *公告删除
     */
    @Transactional
    public ResultBean<Object> deleteAdvert(String accessToken, Long id) {
        LOG.info("AnnouncementService deleteAdvert accessToken={},id={}", accessToken, id);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            if (id == null) {
                result.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return result;
            }
            Optional<Announcement> announcementOptional = announcementRepository.findById(id);
            if (announcementOptional == null) {
                ResultBean.failedResultWithMsg("公告不存在或已删除");
            }
            Announcement announcement = announcementOptional.get();
            List<String> paths = getImgSrc(announcement.getContent());
            paths.add(announcement.getHomePic());
            for (String path : paths) {
                path = path.replaceAll(endpoint + "/", "");
                path = path.split("\\?")[0];
                ossService.deleteObject(bucket, path);
            }
            announcementRepository.deleteById(announcement.getId());
            redisTemplate.delete("saas:announcement:view:" + announcement.getId());
            redisTemplate.delete("saas:announcement:thumb:" + announcement.getId());
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }


    /**
     * 富文本图片上传
     *
     * @param file
     * @return
     */
    public Map<String, Object> uploadDetailFile(MultipartFile file) {
        try {
            if (file == null) {
                return null;
            }
            ResultBean<Object> objectResultBean = ossService.putFile(bucket, file, OSSUploadFileTypeEnum.AD.toString());
            String picUrl = String.valueOf(objectResultBean.getResultData());
            String ossFilePath = ossService.getOssFilePath(picUrl);
            Map<String, Object> resultMap = new HashMap<>();
            if (StringUtils.isBlank(ossFilePath)) {
                return resultMap;
            }
            resultMap.put("url", ossFilePath);
            System.out.println(resultMap.get("url").toString());
            return resultMap;
        } catch (Exception e) {
            LOG.error("图片详情上传失败异常" + e.getMessage(), e);
            return null;
        }
    }

    /**
     * 富文本图片删除
     */
    public void deleteDetailFile(String pathStr) {
        try {
            if (StringUtils.isBlank(pathStr)) {
                return;
            }
            String paths[] = pathStr.split(",");
            for (String path : paths) {
                path = path.replaceAll(endpoint + "/", "");
                path = path.split("\\?")[0];
                ossService.deleteObject(bucket, path);
            }
        } catch (Exception e) {
            LOG.error("图片删除异常" + e.getMessage(), e);
        }
    }

    /*
     *图文信息处理
     */
    private List<String> getImgSrc(String htmlStr) {


        List<String> pics = new ArrayList<String>();
        if (htmlStr == null) {
            return pics;
        }

        String img = "";
        Pattern p_image;
        Matcher m_image;


        String regEx_img = "<img.*src\\s*=\\s*(.*?)[^>]*?>";
        p_image = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
        m_image = p_image.matcher(htmlStr);
        while (m_image.find()) {
            img = img + "," + m_image.group();
            Matcher m = Pattern.compile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(img);
            while (m.find()) {
                pics.add(m.group(1));
            }
        }
        return pics;
    }

    /*
     *公告发布
     */
    public ResultBean<Object> save(String accessToken, AnnouncementVO vo, MultipartFile file) {
        LOG.info("AnnouncementService save accessToken={},vo={},file={}", accessToken, vo.toString(), file);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            // 优化直接默认展示公告
            vo.setStatus(1);
            if (StringUtils.isBlank(vo.getTitle())) {
                LOG.warn("AdvertisementService save title is NULL");
                return ResultBean.failedResultOfParamWithMsg("公告标题不能为空!");
            }
            if (vo.getType() == null) {
                LOG.warn("AdvertisementService save type is NULL");
                return ResultBean.failedResultOfParamWithMsg("公告类型不能为空!");
            }
            if (file == null) {
                LOG.warn("AdvertisementService save file is NULL");
                return ResultBean.failedResultOfParamWithMsg("附件不能为空!");
            }

            ResultBean<Object> objectResultBean = ossService.putFile(bucket, file, OSSUploadFileTypeEnum.AD.toString());
            String picUrl = String.valueOf(objectResultBean.getResultData());
            String homePic = ossService.getOssFilePath(picUrl);

            AnnouncementVO entity = new AnnouncementVO();
            entity.setOrgId(tokenRedisVo.getEnterpriseId());
            entity.setType(vo.getType());
            entity.setReleaseTime(new Date());
            entity.setTitle(vo.getTitle());
            entity.setHomePic(picUrl);
            entity.setOperationId(tokenRedisVo.getId());
            entity.setContent(vo.getContent());

            switch (vo.getType()) {
                case 1:
                    entity.setStatus(0);
                    break;
                case 2:
                    if (vo.getAreaId() == null) {
                        return ResultBean.failedResultWithMsg("社区不能为空");
                    }
                    entity.setAreaId(vo.getAreaId());
                    //展示限制：0 APP不展示  1 无限制
                    entity.setStatus(vo.getStatus());
                    break;
                case 3:
                    if (vo.getCommunityId() == null) {
                        return ResultBean.failedResultWithMsg("小区不能为空");
                    }
                    entity.setCommunityId(vo.getCommunityId());
                    //展示限制：0 APP不展示  1 无限制
                    entity.setStatus(vo.getStatus());
                    break;
            }

            Announcement announcement = new Announcement();
            BeanUtils.copyProperties(entity, announcement);
            Announcement save = announcementRepository.save(announcement);

            if (save != null) {
                redisTemplate.opsForValue().increment("saas:announcement:view:" + save.getId(), 0);
                redisTemplate.opsForValue().increment("saas:announcement:thumb:" + save.getId(), 0);
            }
        } catch (Exception e) {
            LOG.error("AnnouncementService save Exception = {}", e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *获取社区列表
     */
    public ResultBean<Object> getCommunityList(String accessToken) {
        LOG.info("AnnouncementService getCommunityList accessToken={}", accessToken);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }

            List<DepartmentHierarchy> dhList = findCommunityList(tokenRedisVo.getEnterpriseId());
            Iterable<Area> areas = areaRepository.findByLevel(5);

            List<DepartmentHierarchyVO> list = new ArrayList<>();

            for (DepartmentHierarchy departmentHierarchy : dhList) {
                DepartmentHierarchyVO vo = new DepartmentHierarchyVO();
                BeanUtils.copyProperties(departmentHierarchy, vo);
                for (Area area : areas) {
                    if (area.getId().equals(vo.getAreaId())) {
                        vo.setAreaName(area.getName());
                    }
                }
                list.add(vo);
            }

            result.setResultData(list);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *获取小区列表
     */
    public ResultBean<Object> getVillageList(String accessToken) {
        LOG.info("AnnouncementService getVillageList accessToken={}", accessToken);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            //List<Long> communityIds = new ArrayList<>();
            //List<DepartmentHierarchy> communityList = findCommunityList(tokenRedisVo.getEnterpriseId());
            //for (DepartmentHierarchy departmentHierarchy : communityList) {
            //    communityIds.add(departmentHierarchy.getAreaId());
            //}
            ////获取社区下所有小区和企业下小区
            //List<Community> villageList = communityRepository.findByCommunityIdInOrOrgId(communityIds, tokenRedisVo.getEnterpriseId());
            //result.setResultData(villageList);
        //    修复小区显示不全 xiaolong 20230315
            Long areaId = null;
            Long enterpriseId = tokenRedisVo.getEnterpriseId();
            DepartmentHierarchy byOrgIdAndStatus = departmentHierarchyRepository.findByOrgIdAndStatus(enterpriseId, 1);
            if (byOrgIdAndStatus != null) {
                areaId = byOrgIdAndStatus.getAreaId();
            }
            String sql = "SELECT * FROM `saas_community` where province_id = ? or city_id = ? or district_id = ? \n" +
                    "or street_id = ? or community_id = ?";
            List<Object> args = new ArrayList<>();
            args.add(areaId);
            args.add(areaId);
            args.add(areaId);
            args.add(areaId);
            args.add(areaId);
            List<Community> villageList = jdbcTemplate.query(sql , new BeanPropertyRowMapper<>(Community.class),args.toArray());
            result.setResultData(villageList);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *获取当前企业下的社区
     */
    public List<DepartmentHierarchy> findCommunityList(Long orgId) {
        DepartmentHierarchy departmentHierarchy = departmentHierarchyRepository.findByOrgId(orgId);
        List<DepartmentHierarchy> departmentHierarchyArrayList = new ArrayList<>();
        try {
            if (departmentHierarchy == null) {
                return departmentHierarchyArrayList;
            } else if (departmentHierarchy != null && departmentHierarchy.getTagId() != null && departmentHierarchy.getTagId() != 5) {
                String sql = " SELECT id FROM ( SELECT t1.id,IF(FIND_IN_SET(parent_id, @pids) > 0,@pids := CONCAT(@pids, ',', id),0) AS ischild FROM ( SELECT id,parent_id FROM `saas_department_hierarchy` t ORDER BY parent_id, id ) t1,(SELECT @pids := ? ) t2 ) t3 WHERE ischild != 0 \n";
                List<Long> ids = jdbcTemplate.queryForList(sql, new Object[]{departmentHierarchy.getId()}, Long.class);
                departmentHierarchyArrayList.addAll(departmentHierarchyRepository.findByIdInAndTagId(ids, (long) 5));
            } else {
                //DepartmentHierarchy presentDepartmentHierarchy = departmentHierarchyRepository.findByOrgId(orgId);
                departmentHierarchyArrayList.add(departmentHierarchy);
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
        return departmentHierarchyArrayList;
    }

}
